#include <Game/Game.h>
#include "Skills/automatic.h"
#include "entity.h"
#include "json/json.h"

void Entity::unlearnSkill(Skill *skill) {
    std::string name = skill->name;
    // delete skill;
    if (this->skillList[name]->hasPrefix("_BuffHelper_")){
        (dynamic_cast<skill::BuffHelper*>(this->skillList[name]))
                ->remove((dynamic_cast<skill::Buff*>(skill))->minor_id);
    }
    this->skillList.erase(name);
    skill->onUnlearn();
}

void Entity::learnSkill(Skill *skill) {
    this->skillList.insert(make_pair(skill->name, skill));
    skill->origin = this;
    skill->onLearn(g);
}

bool Entity::hasSkill(const std::string &name) {
    return skillList.find(name) != skillList.end();
}

void Entity::useSkill(Skill *skill, const std::vector<std::string> &params) {
    if (skill->canUse(g, params)) {
        skill->use(g, params);
        if (!skill->hasPrefix("Automatic") && !skill->hidden)
            this->g->PerformedSkills.push_back(std::make_tuple(this->id, skill->name, params));
    }
    else {
        std::cerr << skill->origin->id << " used " << skill->name << " failed." << std::endl;
        std::cerr << "params are ";
        for (auto i: params)
            std::cerr << i << " ";
        std::cerr << std::endl;
    }
}

void Entity::useSkill(const std::string &name, const std::vector<std::string> &params) {
	if (skillList.find(name) == skillList.end()) {
        //std::cout << "Skill " << name << " not exists." << std::endl;
        return;
    }
    useSkill(skillList[name], params);
}

void Entity::useLater(const std::string &name, const std::vector<std::string> &params) {
    if (skillList.find(name) == skillList.end())
        return;
    g->SkillCallQueue[skillList[name]->turn].push(
            make_tuple(this, name, params)
    );
}

Json::Value Entity::toJson() {
    Json::Value root = PrefixObject::toJson();
    root["id"] = this->id;
    for (auto &i:skillList) if (i.second->hasPrefix("Buff") || i.second->hasPrefix("CoolDownSkill")){
        root["skillList"][i.first] = i.second->toJson();
    }
    for (auto &i:properties){
        root["properties"][i.first] = i.second;
    }
    return root;
}

Entity::~Entity() {
    for (auto i: skillList){
        delete i.second;
    }
}

